<?php
namespace  App\Services;
// 使用 Guzzle 做请求操作
use GuzzleHttp\Client;
// 支付宝APP 第三方登录
// 特点：相比微信，支付宝所有敏感信息都在服务端完成， 保证了安全
//
// 流程：
// 1.服务端到APP infoStr
// 2.APP端 通过infoStr 获得 auth_code
// 3.服务端通过 auth_code 拿到请求 token
// 4.服务端通过 token 获得用户信息
class AliLogin{
    protected $app_id = '9021000129608907';
    protected $pid = '2088721015219200';
    protected $private_key = 'MIIEowIBAAKCAQEAknDfUCSwAr86JU7c72Qm7VbpJn3qcsMTveyqCvaA7+Y01LuTMpyR8Pl8cP9YltRjAZp3F3V+dBeJivJTI/tx2PhDk2GdZpNf2iGkGLEEMPc36fqi56tkQFsYWWZQWoE3vubgmm91D/FWNk84mQsa2IMtSlFYRbHMjs927sTmMv9mVVIdk9htVjjk6WSYmbzacux3y9xwnrSKgoJE3GN9aecevCO2b8TEQAvF1hOAMvdh1mIBLMWEArUUbk78RK6jrRSFKBsGzyz/kAJiUpbfg35QTp8RUorGv5dNYvyMGVbeiCfASv9HCauupqJlOLB22oNaxVaI9zgHvJu6DsP3IQIDAQABAoIBAH0WBOpELERsa5JqprWlasrYrha+/4A/uaFFgooSvVgt33rHLpjQvKiFsxIiSt2rVVaNRqS3K+imIkqZawMVSM34YmCFxRlVUU7V5YFh0x6wTQaDnJse/2cpaMcUahakwaVDOR8xjWCs2ONTEBlKLwg6JHmSuj/t+7kQ5ZpWffuYelxcNyC3FWPnmed8mRLoS8a51d+FR1UBnM2i5rExXZMVTMYJs5FVZX93q+DW/3lkkhqp5rQwiR5t6G/7CLD6vuW8IvklpzcaE0F+LsK2Rcm6UxmjVBCtAQndOdi4aHUcQqWa55azwYl09304DZB0KgdonJwHQYAUwlAf0BNbmQECgYEAwurLK8jsOMNdvcw38Rt7bt6nYHDDUdwpx7A0QvwPczK/+Ljr29s3Dwd3yqE1fYashwECGCur/9PTr+KzD+e4rBUrF2kE/oyiMJMsjDDkPJ3x46FzHj+3QtN4WBj/B1CfQH4uTzUETZEUBvPZEPBvNKGGeGon0r+4HlyBcdOaE1kCgYEAwFUTq0pDYGgQ4xuI9FKoqu4BGKFOwh4XJU92LPQ/jufFDD3oHE8J4YoHMFfY3m8thC/GYIjZlDY9BhgF1RO4okIEDxiyaTlDHEY8SkiHCymYXZXkkLwBn0rwBYYNPqBXzbySokQwiHlsIixb2w6lDMGebEbcQvqKIEQygAtncQkCgYAwKFKKPtoeLCa8/ffUWjXk7p3r9fBMCVlJPP+sjRpEHAXSLd4YM9EmpXGzXqEYom197YHW9vNIAc4LZrdW9qlp2tEKt6fEPHrWBYa8HFhHob5hv0Hx90wP9q+FFKft5r1x8br/Vtn5UB7imNzIkp7nIgFXPuMX7sZOugxBU0Z+AQKBgQC0rnf236IiLEFJCTIEzK5VPZfcCpXReLEnxNlw69fVqVgM4w9toLbYoXGVccFzXSB2YOdNAuLcAIQdeG3qOUenbrsfb4UTos6v/i9fXXk3/FB+AnWhnm0rtxt7JO7GWZ2C0lcyhzrMyrzR8bgtNznInQ/2Ci+b4H/oRgjnD0+S+QKBgGasjUBRiRi5S6OaG3qYQyI5EGSx9k+jniRZTiTO1Oic+0tWqbx8v1df9to+iK6U1czN1teyy6GlrG3weSdoD2lzPD1qB0JjUkvY36iyNs+ksmWxoMpmqDI+4AOg94gUG3hKTtGvFEO8Dbj8QAK1pY0TnlRlTEdEkbJ6zTsAGTpS';
    /**
     * InfoStr APP登录需要的的infostr
     *
     * @return String
     */
    public function infoStr()
    {
        $infoStr = http_build_query([
            'apiname' => 'com.alipay.account.auth',
            'method' => 'alipay.open.auth.sdk.code.get',
            'app_id' => $this->app_id,
            'app_name' => 'mc',
            'biz_type' => 'openservice',
            'pid' => $this->pid,
            'product_id' => 'APP_FAST_LOGIN',
            'scope' => 'kuaijie',
            'target_id' => mt_rand(999, 99999), //商户标识该次用户授权请求的ID，该值在商户端应保持唯一
            'auth_type' => 'AUTHACCOUNT', // AUTHACCOUNT代表授权；LOGIN代表登录
            'sign_type' => 'RSA2',
        ]);
        $infoStr .= '&sign='.$this->enRSA2($infoStr);
        return $infoStr;
    }
    /**
     * AlipayToken 获得用户 请求token, 通过它获得 用户信息
     *
     * 需要按照支付宝加签流程来。
     */
    public function userInfo($app_auth_token)
    {
        $infoArr = [
            'method' => 'alipay.system.oauth.token',
            'app_id' => $this->app_id,
            'charset' => 'utf-8',
            'sign_type' => 'RSA2',
            'timestamp' => date('Y-m-d H:i:s'),
            'version' => '1.0',
            'code' => $app_auth_token,
            'grant_type' => 'authorization_code',
        ];
        $signStr = $this->myHttpBuildQuery($infoArr);
        $sign = urlencode($this->enRSA2($signStr));
        $qureStr = $signStr.'&sign='.$sign;
        $res = new Client();
//        $body = $res->get('https://openapi.alipay.com/gateway.do?'.$qureStr)->getBody()->getContents();
        $body = $res->get('https://openapi-sandbox.dl.alipaydev.com/gateway.do?'.$qureStr)->getBody()->getContents();
        $body = json_decode($body);
        if (!isset($body->alipay_system_oauth_token_response->access_token)) {
            return '接口异常';
        } else {
            $autho_token = $body->alipay_system_oauth_token_response->access_token;
            $userinfo = $this->aliPayUserInfo($autho_token);
            return $userinfo; // 或则 返回 json_encode($userinfo) 根据实际需求来
        }
    }
    /**
     * AliPayUserInfo 通过 token 获取用户信息
     */
    private function aliPayUserInfo($autho_token)
    {
        $infoArr = [
            'method' => 'alipay.user.info.share',
            'app_id' => $this->app_id,
            'charset' => 'utf-8',
            'sign_type' => 'RSA2',
            'timestamp' => date('Y-m-d H:i:s'),
            'version' => '1.0',
            'auth_token' => $autho_token,
        ];
        $signStr = $this->myHttpBuildQuery($infoArr);
        $sign = urlencode($this->enRSA2($signStr));
        $qureStr = $signStr.'&sign='.$sign;
        $res = new Client();
        $body = $res->get('https://openapi.alipay.com/gateway.do?'.$qureStr)->getBody()->getContents();
        $body = json_decode($body);
        if (!isset($body->alipay_user_info_share_response)) {
            return '接口异常';
        }
        $body = $body->alipay_user_info_share_response;
        return $body;
    }
    /**
     * enRSA2 RSA加密
     *
     * @param String $data
     * @return String
     */
    private function enRSA2($data)
    {
        $str = chunk_split(trim($this->private_key), 64, "\n");
        $key = "-----BEGIN RSA PRIVATE KEY-----\n$str-----END RSA PRIVATE KEY-----\n";
        // $key = file_get_contents(storage_path('rsa_private_key.pem')); 为文件时这样引入
        $signature = '';
        $signature = openssl_sign($data, $signature, $key, OPENSSL_ALGO_SHA256)?base64_encode($signature):NULL;
        return $signature;
    }
    /**
     * myHttpBuildQuery 返回一个 http Get 传参数组
     * 之所以不用 自带函数 http_build_query 时间带 ‘:’ 会被转换
     *
     * @param Array
     * @return String
     */
    private function myHttpBuildQuery($dataArr)
    {
        ksort($dataArr);
        $signStr = '';
        foreach ($dataArr as $key => $val) {
            if (empty($signStr)) {
                $signStr = $key.'='.$val;
            } else {
                $signStr .= '&'.$key.'='.$val;
            }
        }
        return $signStr;
    }
}
